home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / ProcDoggie 1.0a6⁄THINK P / UDialogUtils.p < prev    next >
Encoding:
Text File  |  1991-02-21  |  26.7 KB  |  666 lines  |  [TEXT/PJMM]

  1. unit UDialogUtils;
  2.  
  3. {-------------------------------------------------------------------------------}
  4. {#}
  5. {#    Apple Macintosh Developer Technical Support}
  6. {#}
  7. {#    Interfaces for the dialog utilities}
  8. {#}
  9. {#    Program:    ProcDoggie}
  10. {#    File:        UDialogUtils.p - Pascal Implementation}
  11. {#}
  12. {#    by:        Forrest Tanaka}
  13. {#}
  14. {#    Copyright © 1988-1991 Apple Computer, Inc.}
  15. {#    All rights reserved.}
  16. {#}
  17. {--------------------------------------------------------------------------------}
  18. {#}
  19. {# This unit is an embryonic version of an alternative to the Dialog Manager.}
  20. {# Why replace the Dialog Manager?  For dialogs with just a few basic items like}
  21. {# some static text and some buttons, the Dialog Manager isn’t too bad.  It still}
  22. {# doesn’t handle low-memory situations at all well nor does it handle cases in}
  23. {# which some resources are missing with much grace, but a small dialog shouldn’t}
  24. {# have too many problems with low-memory situations and clever memory}
  25. {# management can avoid all problems, and missing resources is an anomalous}
  26. {# situation.  The Dialog Manager exposes its problems once a dialog starts to}
  27. {# get a bit complicated.  User items and controls become difficult to manage,}
  28. {# and even something as simple as a static text item that’s in a different size}
  29. {# or style becomes a major hassle to implement.  The ictb mechanism introduced}
  30. {# on Color QuickDraw machines was supposed to make it easier to specify static}
  31. {# and edit text styles, but this mechanism is so buggy that it’s useless in my}
  32. {# opinion.  Another problem with the Dialog Manager is its slow performance when}
  33. {# drawing items.  Technical Note #203 “Don’t Abuse the Managers” has many words}
  34. {# of wisdom when it comes to the Dialog Manager, like don’t use it.}
  35. {#}
  36. {# Of course, the usual reply we get to this is, “But ResEdit’s DITL editor makes}
  37. {# arranging dialogs so easy!”  This is true, and I think it’s a compelling}
  38. {# argument.  This also makes localization very easy, which isn’t a trivial}
  39. {# concern.  But who said that only the Dialog Manager can read DITLs?  The}
  40. {# structure of a DITL is very well-defined, and couldn’t possibly change without}
  41. {# breaking every program that put up an alert box.  DITL resources aren’t that}
  42. {# complicated, and your own program can read them as well as the Dialog}
  43. {# Manager——better probably.}
  44. {#}
  45. {# That’s what this unit does.  It reads in a DITL, creates an internal item list}
  46. {# based on what it found in the DITL, then attaches this item list to the}
  47. {# "items" field of a DialogRecord.  This unit also contains routines to draw the}
  48. {# items and routines to set static text items.  And it does this while checking}
  49. {# for errors; what a concept!}
  50. {#}
  51. {# But, as I said, this unit is very embryonic.  The first time I tried this, I}
  52. {# made it very complete, but I also made it much, much harder to use than the}
  53. {# Dialog Manager.  So, I almost completely stripped it for the purposes of this}
  54. {# sample application.  Now, it only handles static text items and buttons, and}
  55. {# it no longer handles modal dialogs.  Eventually, I want to give this the full}
  56. {# functionality of the real Dialog Manager.}
  57. {#}
  58. {# One capability this unit has that the Dialog Manager doesn’t implement is}
  59. {# style information for static text items.  I don’t mean one static text item}
  60. {# with multiple text styles.  I mean different items can have different text}
  61. {# styles.  Doing this through the Dialog Manager involves much more work than}
  62. {# it should.  The way I do this while keeping the DITL structure is to use the}
  63. {# four bytes used for a placeholder for handle or procedure pointer in Inside}
  64. {# Macintosh I page 427.  If you want static text items displayed in the standard}
  65. {# font, style, and justification, then just leave these four bytes set to 0.  If}
  66. {# you want to specify the type face, style, size, and line justification, then}
  67. {# each of these four bytes can hold each of these pieces of information.}
  68. {#}
  69. {# The first byte holds a font index.  This isn’t a font number because, as}
  70. {# Technical Note #191 “Font Names” says, it isn’t nice to save font numbers.}
  71. {# This font index is an index into a STR# resource which contains the names of}
  72. {# whatever fonts you want to use in this dialog.  For example, if the second}
  73. {# string in the STR# resource is "Monaco", then a 2 placed into the font index}
  74. {# field will cause the DrawDialogItems routine defined in this unit to display}
  75. {# that static text item in Monaco.  The STR# resource should have a resource ID}
  76. {# of 0.  This lets all dialog boxes use the same font list.  You can override}
  77. {# this font list by specifying a STR# resource with an ID equal to the resource}
  78. {# ID of the DITL being read.  In this way, you can provide a STR# resource ID 0}
  79. {# that contains the default font list, and then provide special font lists for}
  80. {# for specific DITLs.}
  81. {#}
  82. {# The second byte holds the style (“face” according to QuickDraw) of the static}
  83. {# text item.  This holds the same value as the Style type.  The third byte}
  84. {# contains the point size of the static text.  The point size is limited to 255,}
  85. {# which shouldn’t be a problem.  The last byte contains the justification of the}
  86. {# static text.  -2 means left justification, -1 means right justification, 0}
  87. {# means default justification, and 1 means center justification.}
  88. {#}
  89. {-------------------------------------------------------------------------------}
  90. {[j=20/57/1$] Pasmat Options}
  91.  
  92. {-------------------------------------------------------------------------------}
  93. {#}
  94. {#     2/21/91 pvh - THINK Pascal conversion.}
  95. {#    Notes:}
  96. {#        A few changes for handling packed records ("Ack, pointer math!").}
  97. {#}
  98. {-------------------------------------------------------------------------------}
  99.  
  100. interface
  101.  
  102.  
  103. (*******************************************************************************}
  104. {* Used Units}
  105. {*******************************************************************************)
  106.  
  107.     uses
  108.         (* Group 1 *)
  109.         Types, QuickDraw, 
  110.  
  111.         (* Group 2 *)
  112.         Controls, Errors, Events, Fonts, Memory, OSUtils, Files, Resources, TextEdit, ToolUtils, 
  113.  
  114.         (* Group 3 *)
  115.         Windows, 
  116.  
  117.         (* Group 4 *)
  118.         Dialogs, 
  119.  
  120.         (* Application *)
  121.         UEmergMem;
  122.  
  123.  
  124. (*******************************************************************************}
  125. {* Constants}
  126. {*******************************************************************************)
  127.  
  128.     const
  129.         kNoItem = -1; {No dialog item is applicable or end of dialog item list}
  130.  
  131.  
  132. (*******************************************************************************}
  133. {* Types}
  134. {*******************************************************************************)
  135.  
  136.     type
  137.         (* Type information for static text items *)
  138.         TypeInfoRec = record
  139.                 typeFace: Integer; {Font number of text}
  140.                 typeSize: Integer; {Font size of text}
  141.                 textJust: Integer; {Justification of text}
  142.                 typeStyle: Style;   {Font style of text}
  143.             end;
  144.  
  145.  
  146. (*******************************************************************************}
  147. {* InstallDialogItems - Install a DITL into a dialog window}
  148. {*}
  149. {* This routine is called to install a DITL into the dialog window specified by}
  150. {* "aDialog".  The resource ID of the desired DITL is specified by "itemListNum".}
  151. {* InstallDialogItems returns noErr if the item list was successfully created and}
  152. {* attached to aDialog, otherwise, an operating system error code is returned.}
  153. {*******************************************************************************)
  154.  
  155.     function InstallDialogItems (aDialog: DialogPtr; itemListNum: Integer): OSErr;
  156.  
  157.  
  158. (*******************************************************************************}
  159. {* SetStatTextItem - Set a static text dialog item to the specified text}
  160. {*}
  161. {* This routine sets the text of a static text item to the text pointed to by}
  162. {* "textPtr" and having the length "textLength".  "aDialog" is a pointer to the}
  163. {* dialog box that this is being done in, and "itemNum" is the item number of the}
  164. {* static text item to set.  If that item isn’t actually a static text item, then}
  165. {* nothing is done.  If there isn’t enough memory to put the text into the static}
  166. {* text item, then nothing is done.}
  167. {*******************************************************************************)
  168.  
  169.     procedure SetStatTextItem (aDialog: DialogPtr; itemNum: Integer; textPtr: Ptr; textLength: Integer);
  170.  
  171.  
  172. (*******************************************************************************}
  173. {* GetStatTextFontInfo - Get font information for a static text item}
  174. {*}
  175. {* This routine gets the font information for the static text item with an item}
  176. {* number of "itemNum" in the dialog specified by "aDialog".  This font}
  177. {* information is returned in "typeInfo".  The the specified item isn’t a static}
  178. {* text item, then nothing is done.}
  179. {*******************************************************************************)
  180.  
  181.     procedure GetStatTextFontInfo (aDialog: DialogPtr; itemNum: Integer; var typeInfo: TypeInfoRec);
  182.  
  183.  
  184. (*******************************************************************************}
  185. {* DrawDialogItems - Draw all standard dialog items}
  186. {*}
  187. {* All standard dialog items in the dialog box pointed to by "aDialog" are drawn.}
  188. {*******************************************************************************)
  189.  
  190.     procedure DrawDialogItems (aDialog: DialogPtr);
  191.  
  192.  
  193. (*******************************************************************************}
  194. {* GetDialogItemRect - Get the item rectangle of a specified dialog item}
  195. {*}
  196. {* This routine gets the item rectangle of the dialog item in the dialog box}
  197. {* specified by "aDialog" and having an item number of "itemNum".  This rectangle}
  198. {* is returned in "itemRect".}
  199. {*******************************************************************************)
  200.  
  201.     procedure GetDialogItemRect (aDialog: DialogPtr; itemNum: Integer; var itemRect: Rect);
  202.  
  203.  
  204. (*******************************************************************************}
  205. {* DisposeDialogItems - Dispose of all dialog items in the specified dialog box}
  206. {*}
  207. {* This routine disposes of the memory used by all the dialog items in the dialog}
  208. {* box specified by "aDialog".  The item list itself is also deallocated.}
  209. {*******************************************************************************)
  210.  
  211.     procedure DisposeDialogItems (aDialog: DialogPtr);
  212.  
  213.  
  214. implementation
  215.  
  216. (*******************************************************************************}
  217. {* Types}
  218. {*******************************************************************************)
  219.  
  220.     type
  221.         TextStRec = packed record
  222. {    TextStRec = record}
  223.                 fontIndex: Byte;       {Index into STR# rsrc of font name for text}
  224.                 statStyle: Byte;       {Style of static text}
  225.                 statSize: Byte;       {Point size of static text}
  226.                 statJust: SignedByte; {Justification of static text}
  227.             end;
  228.  
  229.         DITLTmplRec = packed record
  230. {    DITLTmplRec = record}
  231.                 pad0: TextStRec;  {Text style for static text items}
  232.                 displayRect: Rect;       {Rect in which to display item in wind coords}
  233.                 itemType: Byte;       {Type of item}
  234.                 dataLen: Byte;       {Length of item data}
  235.                 case Integer of
  236.                     0: (
  237.                             itemRes: Integer
  238.                     );
  239.                     1: (
  240.                             itemText: packed array[0..239] of Char
  241.                     )
  242.             end;
  243.         DITLTmplPtr = ^DITLTmplRec;
  244.  
  245.         ItemRec = record
  246.                 displayRect: Rect;        {Display item rect in window coords}
  247.                 refCon: LongInt;     {Used for anything client wants}
  248.                 dismissor: Boolean;     {True if the item is a dismissor}
  249.                 case itemType : Integer of {Code for item type or 0 if last item}
  250.                     0: (
  251.                             itemControl: ControlHandle
  252.                     ); {Handle to item control}
  253.                     1: (
  254.                             itemText: Handle;         {Handle to text of static text}
  255.                             itemTypeInfo: TypeInfoRec
  256.                     )    {Type info for static text}
  257.             end;
  258.         ItemListArr = array[0..255] of ItemRec;
  259.         ItemListPtr = ^ItemListArr;
  260.         ItemListHnd = ^ItemListPtr;
  261.  
  262.  
  263. {$S DialogUtils}
  264. (*******************************************************************************}
  265. {* Public: InstallDialogItems}
  266. {*}
  267. {* This routine is mainly a DITL-resource interpreter.  After loading the DITL}
  268. {* resource with a resource ID passed in itemListNum into memory, it reads the}
  269. {* information in it to build up an array of dialog items in an ItemListArr,}
  270. {* which is defined in the TYPE section of this source file.  This routine}
  271. {* allocates the item array and attaches it to the "items" field of the specified}
  272. {* DialogRecord.  Once the item array is filled, the DITL is no longer needed and}
  273. {* is made purgeable.}
  274. {*}
  275. {* Currently, this routine handles push buttons and static text fields.  Push}
  276. {* buttons are simply handled by calling NewControl.  The resulting ControlHandle}
  277. {* is placed into the itemControl field of the ItemRec.  For static text items,}
  278. {* a handle to the text is placed into itemText and the style information is}
  279. {* placed into the itemTypeInfo.}
  280. {*}
  281. {* Static text items are handled a little differently, and involves a change to}
  282. {* the DITL structure.  I’ve kept the size of the DITL the same as it ever was,}
  283. {* but the four bytes that are described as a “placeholder for handle or}
  284. {* procedure pointer” on page 427 of Inside Macintosh I are now interpreted by}
  285. {* InstallDialogItems to hold font information for static text items.  This font}
  286. {* information has the structure described by TextStRec which is declared in the}
  287. {* TYPE section of this source file.  This is a four-byte record that holds the}
  288. {* type face, type style, type size, and justification (really alignment) of the}
  289. {* static text item.  InstallDialogItems converts this into a TypeInfoRec}
  290. {* (declared in the UDialogUtils.p file) which is then placed into the item}
  291. {* array.  When DrawDialogItems is called, it draws static text items using this}
  292. {* font information.}
  293. {*}
  294. {* The TextStRec consists of four bytes.  The first bytes specifies the type}
  295. {* face to use for the static text.  It doesn’t specify the font number because}
  296. {* font numbers for a particular type face can vary from system to system.}
  297. {* Instead, this field holds an index into a STR# resource which holds a list of}
  298. {* font names.  The STR# resource must have a resource ID equal to the resource}
  299. {* ID of the DITL being read, that is, "itemListNum."}
  300. {*}
  301. {* The second byte specifies the style that the static text is meant to be drawn}
  302. {* in.  It holds the same value as the Style type.  The Style type is 16 bits}
  303. {* wide, so I declared this field as a Byte instead.  The third byte specifies}
  304. {* the size of text to use.  Of course, being a byte, it’s limited to a point}
  305. {* size of 255 points.  I didn’t think that’d be much of a problem, and you can}
  306. {* always draw the text yourself if you needed something larger.  The last byte}
  307. {* specifies the alignment of text in the static text item rectangle.  This field}
  308. {* can have the values teFlushRight, teFlushLeft, teFlushDefault, and teCenter.}
  309. {*}
  310. {* I wanted to keep the DITL mechanism so that Rez and particularly ResEdit could}
  311. {* still be used to edit the DITL, even though the Dialog Manager isn’t being}
  312. {* used with these kinds of dialogs.  Unfortunately, I had to redefine the Rez}
  313. {* DITL template so that it could take the static text font information, and}
  314. {* worse, ResEdit won’t edit DITLs that have non-zero values in the location that}
  315. {* I’m reading the font information.  So, keeping the DITL isn’t any particular}
  316. {* advantage over defining a completely new structure.  But, I’ll leave it this}
  317. {* ways for now.  There ARE other resource editors that might not be quite so}
  318. {* quick to criticize my DITLs.}
  319. {*}
  320. {* If all the dialog items were installed correctly, then noErr is returned.  If}
  321. {* any error happend, then the operating system result code is returned and the}
  322. {* dialog item list is disposed of, leaving aDialog unaffected.}
  323. {*******************************************************************************)
  324.  
  325.     function InstallDialogItems (aDialog: DialogPtr; itemListNum: Integer): OSErr;
  326.  
  327.         type
  328.             IntPtr = ^Integer;
  329.  
  330.         var
  331.             numItems: Integer;       {Number of items in item list}
  332.             itemNum: Integer;       {Item number of item we’re installing}
  333.             itemKind: Integer;       {Type of the item}
  334.             fontNumber: Integer;       {Font number of static text item}
  335.             ditlItemPtr: DITLTmplPtr;   {Pointer to each item}
  336.             ditlList: Handle;        {Handle to DITL resource}
  337.             itemList: ItemListHnd;   {Handle to the item list}
  338.             aControl: ControlHandle; {Handle to a control we’re installing}
  339.             aString: Str255;        {String used for a couple of things}
  340.             staticText: Handle;        {Handle to text for static text item}
  341.             dataLen: Integer;       {Length of item data, rounded up to even}
  342.             doesDismiss: Boolean;       {True if the item is a dismissor}
  343.         procedure RecoverError (error: Integer);
  344.  
  345.         begin
  346.             if ditlList <> nil then
  347.                 begin
  348.                     HUnlock(ditlList);
  349.                     HPurge(ditlList)
  350.                 end;
  351.             if itemList <> nil then
  352.                 DisposeDialogItems(aDialog);
  353.             DialogPeek(aDialog)^.items := nil;
  354.             InstallDialogItems := error;
  355.             EXIT(InstallDialogItems)
  356.         end;
  357.  
  358.     begin
  359.         ditlList := nil;
  360.         itemList := nil;
  361.  
  362.         (* Grab the requested DITL resource *)
  363.         ditlList := GetResource('DITL', itemListNum);
  364.         if ditlList = nil then
  365.             if ResError = noErr then
  366.                 RecoverError(resNotFound)
  367.             else
  368.                 RecoverError(ResError);
  369.  
  370.         (* Make sure we don’t lose it while we’re reading from it *)
  371.         HNoPurge(ditlList);
  372.  
  373.         (* Allocate item list; add 1 for flag record and 1 for numItems-1 adj *)
  374.         numItems := IntPtr(ditlList^)^;
  375.         itemList := ItemListHnd(NewHandleMargin(SIZEOF(ItemRec) * (numItems + 2), kAllocApp, not kAllocClr));
  376.         if itemList = nil then
  377.             RecoverError(memFullErr);
  378.  
  379.         (* Fill with kNoItem items in case of error while building item list *)
  380.         for itemNum := 0 to numItems + 1 do
  381.             itemList^^[itemNum].itemType := kNoItem;
  382.  
  383.         (* Put the item list into the dialog record *)
  384.         DialogPeek(aDialog)^.items := Handle(itemList);
  385.  
  386.         (* Point at the first item in the DITL *)
  387.         HLock(ditlList);
  388.         ditlItemPtr := DITLTmplPtr(ORD4(ditlList^) + SIZEOF(Integer));
  389.  
  390.         (* For each item in DITL, install into item list *)
  391.         for itemNum := 0 to numItems do
  392.             begin
  393.                 (* Get the type of the item *)
  394.                 itemKind := ditlItemPtr^.itemType;
  395.  
  396.                 (* If itemDisable flag clear, item is a dismissor *)
  397.                 if itemKind < 128 then
  398.                     doesDismiss := TRUE
  399.                 else
  400.                     begin
  401.                         doesDismiss := FALSE;
  402.                         itemKind := itemKind - 128
  403.                     end;
  404.  
  405.                 (* Grab the item information *)
  406.                 if itemKind = ctrlItem + btnCtrl then
  407.                     begin
  408.                         (* Copy control’s title to controlTitle *)
  409.                         BlockMove(@aString, @aString, ditlItemPtr^.dataLen + 1);
  410. {$IFC THINK_PASCAL}
  411. { 2/21/91 pvh - THINK P can't handle packed types }
  412.                         BlockMove(Ptr(ord(ditlItemPtr) + 13), @aString, ditlItemPtr^.dataLen + 1);
  413. {$ELSEC}
  414.                         BlockMove(@ditlItemPtr^.dataLen, @aString, ditlItemPtr^.dataLen + 1);
  415. {$ENDC}
  416.                         (* Create the new control *)
  417.                         aControl := NewControl(aDialog, ditlItemPtr^.displayRect, aString, TRUE, 0, 0, 0, pushButProc, 0);
  418.  
  419.                         (* Put the control’s handle into our item list *)
  420.                         itemList^^[itemNum].itemType := itemKind;
  421.                         itemList^^[itemNum].itemControl := aControl;
  422.  
  423.                         (* Bail if there’s not enough memory *)
  424.                         if FailLowMemory(0) then
  425.                             RecoverError(memFullErr)
  426.                         else if aControl = nil then
  427.                             if (ResError = noErr) | (ResError = resNotFound) then
  428.                                 RecoverError(resNotFound)
  429.                             else
  430.                                 RecoverError(ResError);
  431.  
  432.                         (* Put the control’s item number into the control’s refCon *)
  433.                         SetCRefCon(aControl, itemNum)
  434.                     end
  435.                 else if itemKind = statText then
  436.                     begin
  437.                         (* Allocate space for text *)
  438.                         staticText := NewHandleMargin(ditlItemPtr^.dataLen, kAllocApp, not kAllocClr);
  439.  
  440.                         (* Put the control’s handle into our item list *)
  441.                         itemList^^[itemNum].itemType := itemKind;
  442.                         itemList^^[itemNum].itemText := staticText;
  443.  
  444.                         (* Bail if there’s not enough memory for the text *)
  445.                         if staticText = nil then
  446.                             RecoverError(memFullErr);
  447.  
  448.                         (* Copy DITL text to our text handle *)
  449.                         BlockMove(@ditlItemPtr^.itemText, staticText^, ditlItemPtr^.dataLen);
  450.  
  451.                         (* Put a handle to the text into our item list *)
  452.                         aString[0] := CHR(0);
  453.                         if ditlItemPtr^.pad0.fontIndex > 0 then
  454.                             begin
  455.                                 GetIndString(aString, itemListNum, ditlItemPtr^.pad0.fontIndex);(*<*)
  456.                                 if aString[0] = CHR(0) then
  457.                                     GetIndString(aString, 0, ditlItemPtr^.pad0.fontIndex)(*<*)
  458.                             end;
  459.                         if aString[0] = CHR(0) then
  460.                             fontNumber := 0
  461.                         else
  462.                             GetFNum(aString, fontNumber); (*<*)
  463.                         itemList^^[itemNum].itemTypeInfo.typeFace := fontNumber;
  464.                         itemList^^[itemNum].itemTypeInfo.typeSize := ditlItemPtr^.pad0.statSize;
  465.                         itemList^^[itemNum].itemTypeInfo.textJust := ditlItemPtr^.pad0.statJust;
  466.  
  467. {$IFC THINK_PASCAL}
  468.                         BlockMove(Ptr(ord(ditlItemPtr) + 1), @itemList^^[itemNum].itemTypeInfo.typeStyle, 1);
  469. {$ELSEC}
  470.                         itemList^^[itemNum].itemTypeInfo.typeStyle := Style(ditlItemPtr^.pad0.statStyle)
  471. {$ENDC}
  472.                     end
  473.                 else
  474.                     itemList^^[itemNum].itemType := itemKind;
  475.  
  476.                 (* Copy interesting characteristics to our item list *)
  477.                 with itemList^^[itemNum] do
  478.                     begin
  479.                         (*WITH*)
  480.                         displayRect := ditlItemPtr^.displayRect;
  481.                         (*WITH*)
  482.                         refCon := 0;
  483.                         (*WITH*)
  484.                         dismissor := doesDismiss
  485.                     end;
  486.  
  487.                 (* Bump the pointer to the next item in the DITL *)
  488.                 dataLen := BAnd(ditlItemPtr^.dataLen + 1, $FFFE);
  489.                 ditlItemPtr := DITLTmplPtr(ORD4(@ditlItemPtr^.itemText) + dataLen)
  490.             end;
  491.  
  492.         (* Don’t need the dialog item list any more *)
  493.         HUnlock(ditlList);
  494.         HPurge(ditlList);
  495.     end;
  496.  
  497.  
  498. {$S DialogUtils}
  499. (*******************************************************************************}
  500. {* Public: SetStatTextItem}
  501. {*}
  502. {* The text of a static text item is specified by a handle to the text, so that}
  503. {* handle is resized to the new text length, if needed, and then the text is}
  504. {* simply BlockMoved in.}
  505. {*******************************************************************************)
  506.  
  507.     procedure SetStatTextItem (aDialog: DialogPtr; itemNum: Integer; textPtr: Ptr; textLength: Integer);
  508.  
  509.         var
  510.             itemList: ItemListHnd; {Handle to item list}
  511.             textHandle: Handle;      {Handle to the existing item text}
  512.  
  513.     begin
  514.         (* Grab the item list from the dialog window’s refCon *)
  515.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  516.  
  517.         (* If the item is indeed a static text item, then set it *)
  518.         if itemList^^[itemNum].itemType = statText then
  519.             begin
  520.                 textHandle := itemList^^[itemNum].itemText;
  521.                 if not FailLowMemory(textLength) then
  522.                     begin
  523.                         if GetHandleSize(textHandle) <> textLength then
  524.                             SetHandleSize(textHandle, textLength);
  525.                         BlockMove(textPtr, textHandle^, textLength)
  526.                     end
  527.             end
  528.     end;
  529.  
  530.  
  531. {$S DialogUtils}
  532. (*******************************************************************************}
  533. {* Public: GetStatTextFontInfo}
  534. {*}
  535. {* Font information for a static text item is simply stored in its itemTypeInfo}
  536. {* field.  It’s a simple matter of copying this record into "typeInfo".}
  537. {*******************************************************************************)
  538.  
  539.     procedure GetStatTextFontInfo (aDialog: DialogPtr; itemNum: Integer; var typeInfo: TypeInfoRec);
  540.  
  541.         var
  542.             itemList: ItemListHnd; {Handle to item list}
  543.  
  544.     begin
  545.         (* Grab the item list from the dialog window’s refCon *)
  546.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  547.  
  548.         (* If the item is indeed a static text item, then set it *)
  549.         if itemList^^[itemNum].itemType = statText then
  550.             typeInfo := itemList^^[itemNum].itemTypeInfo
  551.     end;
  552.  
  553.  
  554. {$S DialogUtils}
  555. (*******************************************************************************}
  556. {* Public: DrawDialogItems}
  557. {*}
  558. {* The item list of a dialog box is stored in the "items" field of the}
  559. {* DialogRecord.  This routine loops through every dialog item and draws whatever}
  560. {* item types it understands.  Currently, this is static text items and icons.}
  561. {*******************************************************************************)
  562.  
  563.     procedure DrawDialogItems (aDialog: DialogPtr);
  564.  
  565.         var
  566.             itemNum: Integer;     {Item number of item we’re installing}
  567.             itemList: ItemListHnd; {Handle to the item list}
  568.             itemRect: Rect;        {Rectangle of dialog item}
  569.             staticText: Handle;      {Handle to static text}
  570.  
  571.     begin
  572.         (* Draw any static text items or icon items in the item list*)
  573.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  574.         itemNum := 0;
  575.         while itemList^^[itemNum].itemType <> kNoItem do
  576.             begin
  577.                 if itemList^^[itemNum].itemType = statText then
  578.                     begin
  579.                         (* Item is a static text item; call TextBox if there’s text *)
  580.                         staticText := itemList^^[itemNum].itemText;
  581.                         if GetHandleSize(staticText) > 0 then
  582.                             begin
  583.                                 TextFont(itemList^^[itemNum].itemTypeInfo.typeFace);
  584.                                 TextSize(itemList^^[itemNum].itemTypeInfo.typeSize);
  585.                                 TextFace(itemList^^[itemNum].itemTypeInfo.typeStyle);
  586.                                 itemRect := itemList^^[itemNum].displayRect;
  587.                                 HLock(staticText);
  588.                                 TextBox(staticText^, GetHandleSize(staticText), itemRect, itemList^^[itemNum].itemTypeInfo.textJust);
  589.                                 HUnlock(statictext)
  590.                             end
  591.                     end;
  592.                 itemNum := itemNum + 1
  593.             end
  594.     end;
  595.  
  596.  
  597. {$S DialogUtils}
  598. (*******************************************************************************}
  599. {* Public: GetDialogItemRect}
  600. {*}
  601. {* The item list of a dialog box is in the "items" field of the DialogRecord.}
  602. {* This handle is retrieved and the displayRect of the specified item into}
  603. {* "itemRect".}
  604. {*******************************************************************************)
  605.  
  606.     procedure GetDialogItemRect (aDialog: DialogPtr; itemNum: Integer; var itemRect: Rect);
  607.  
  608.         var
  609.             itemList: ItemListHnd; {Handle to item list}
  610.  
  611.     begin
  612.         (* Grab the item list from the dialog window’s refCon *)
  613.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  614.  
  615.         (* Copy the item’s display rectangle *)
  616.         itemRect := itemList^^[itemNum].displayRect
  617.     end;
  618.  
  619.  
  620. {$S DialogUtils}
  621. (*******************************************************************************}
  622. {* Public: DisposeDialogItems}
  623. {*}
  624. {* A handle to the dialog box’s dialog item list is retrieved from the}
  625. {* DialogRecord’s "items" handle.  The type of each item is checked, and the}
  626. {* memory taken by that item is disposed of appropriately.}
  627. {*******************************************************************************)
  628.  
  629.     procedure DisposeDialogItems (aDialog: DialogPtr);
  630.  
  631.         var
  632.             itemNum: Integer;     {Item number of item we’re installing}
  633.             itemList: ItemListHnd; {Handle to the item list}
  634.  
  635.     begin
  636.         (* Grab the item list from the dialog window’s refCon *)
  637.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  638.  
  639.         (* Starting at item 1, go through entire list and dispose of each item *)
  640.         if itemList <> nil then
  641.             begin
  642.                 itemNum := 0;
  643.                 while itemList^^[itemNum].itemType <> kNoItem do
  644.                     begin
  645.                         with itemList^^[itemNum] do
  646.                             begin
  647.                                 if itemType = ctrlItem + btnCtrl then (*WITH*)
  648.                                     begin
  649.                                         if itemControl <> nil then (*WITH*)
  650.                                             DisposeControl(itemControl)(*WITH*)
  651.                                     end
  652.                                 else if itemType = statText then (*WITH*)
  653.                                     begin
  654.                                         if itemText <> nil then (*WITH*)
  655.                                             DisposHandle(itemText)(*WITH*)
  656.                                     end
  657.                             end;
  658.  
  659.                         (* Go on to the next item in the item list *)
  660.                         itemNum := itemNum + 1
  661.                     end;
  662.                 DisposHandle(Handle(itemList))
  663.             end
  664.     end;
  665.  
  666. end.